package week3
//reference https://blog.csdn.net/qq_41257365/article/details/115362700
//reference https://mp.weixin.qq.com/s/GpVy1eB5Cz_t-dhVC6BJNw
import (
	"context"
	"fmt"
	xerr "github.com/pkg/errors"
	"golang.org/x/sync/errgroup"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"
)

func Homework() {
	g, ctx := errgroup.WithContext(context.Background())
	//通过 web, /shutdown ,关闭 server
	webServerOut := make(chan struct{})

	//定义单 server
	mux := http.NewServeMux()
	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("hello"))
	})
	mux.HandleFunc("/shutdown", func(w http.ResponseWriter, r *http.Request) {
		//这里会发送 chan ,用来终止 server
		webServerOut<- struct{}{}
	})
	server := http.Server{
		Handler: mux,
		Addr: ":8080",
	}
	//启动 server
	g.Go(func() error {
		return server.ListenAndServe()
	})
	g.Go(func() error {
		select {
		case <- ctx.Done():
			println("server exit via context1")
		case <-webServerOut:
			println("server exit via web")
		}
		ctxTO, cancel := context.WithTimeout(context.Background(), 3*time.Second)
		defer cancel()
		return xerr.Wrap(server.Shutdown(ctxTO), "shutdown server")
	})
	g.Go(func() error {
		exit := make(chan os.Signal)
		signal.Notify(exit, syscall.SIGINT, syscall.SIGTERM)
		select {
		case <- ctx.Done():
			return xerr.Wrap(ctx.Err(), "server exit via context2")
		case s := <- exit:
			return xerr.Wrap(xerr.New("server exit via signal"), s.String())
		}
	})
	//等待 go 都完成,有错误就打印错误, 错误用 errors.Wrap包装
	if err := g.Wait();err != nil{
		fmt.Printf("errgroup exit err %+v", err)
	}
}